package ch.uzh.ifi.sonar.storage;

import java.io.File;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

import ch.uzh.ifi.sonar.Activator;
import ch.uzh.ifi.sonar.analyzers.StreamAnalyzer;
import ch.uzh.ifi.sonar.model.ModelFactory;
import ch.uzh.ifi.sonar.model.Project;
import ch.uzh.ifi.sonar.model.Source;
import ch.uzh.ifi.sonar.model.Stream;
import ch.uzh.ifi.sonar.util.SonarUtility;

public class StoragePreferencePage extends FieldEditorPreferencePage implements
		IWorkbenchPreferencePage {

	// TODO automation of creating integration view and mapping to drives.
	public static List<List<String>> STREAMS ;
	public static List<String> TITLES;

	private IPreferenceStore store;

	private Table streamTable;

	private Composite fieldEditorParent;

	public StoragePreferencePage() {
		super(GRID);
		setPreferenceStore(Activator.getDefault().getPreferenceStore());
		setDescription("Here you can define the Storage Preferences");
		this.fieldEditorParent = getFieldEditorParent();
		STREAMS = SonarUtility.readStreamContent();
		TITLES = SonarUtility.readStreamsHeader();

	}
	

	@Override
	public void init(IWorkbench workbench) {
		store = getPreferenceStore();
		store.setDefault(PreferenceConstants.STORAGE_NAMESPACE, "SONAR_Storage");
		store.setDefault(PreferenceConstants.STORAGE_URI,
				"jdbc:mysql://127.0.0.1:3306");
		store.setDefault(PreferenceConstants.STORAGE_DB, "sonar_db");
		store.setDefault(PreferenceConstants.STORAGE_DRIVER,
				"com.mysql.jdbc.Driver");
		store.setDefault(PreferenceConstants.STORAGE_USER, "root");
		store.setDefault(PreferenceConstants.STORAGE_PW, "password");

	}

	@Override
	protected Control createContents(Composite parent) {
		fieldEditorParent = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		fieldEditorParent.setLayout(layout);
		fieldEditorParent.setFont(parent.getFont());

		createFieldEditors();
		createButtonGroup();
		createStreamTableGroup();
		initialize();
		checkState();
		return fieldEditorParent;
	}

	@Override
	protected void createFieldEditors() {

		addField(new StringFieldEditor(PreferenceConstants.STORAGE_NAMESPACE,
				"&Namespace:", 60, fieldEditorParent));

		addField(new StringFieldEditor(PreferenceConstants.STORAGE_URI,
				"&URL:", 60, fieldEditorParent));

		addField(new StringFieldEditor(PreferenceConstants.STORAGE_DB,
				"&Database:", 30, fieldEditorParent));

		addField(new StringFieldEditor(PreferenceConstants.STORAGE_DRIVER,
				"&JDBC Driver:", 60, fieldEditorParent));

		addField(new StringFieldEditor(PreferenceConstants.STORAGE_USER,
				"&Username:", 60, fieldEditorParent));

		addField(new StringFieldEditor(PreferenceConstants.STORAGE_PW,
				"&Password:", 60, fieldEditorParent));

	}

	private void createButtonGroup() {
		if (fieldEditorParent != null) {
			final Group buttonGroup = new Group(fieldEditorParent.getParent(),
					SWT.NONE);
			GridLayout gridLayout = new GridLayout();
			gridLayout.numColumns = 3;
			buttonGroup.setLayout(gridLayout);
			GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
			buttonGroup.setLayoutData(gridData);

			Button newDbButton = new Button(buttonGroup, SWT.PUSH);
			newDbButton.setText("create the database");
			newDbButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
					true));

			Button clearButton = new Button(buttonGroup, SWT.PUSH);
			clearButton.setText("drop the database");
			clearButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
					true));

			Button importAllButton = new Button(buttonGroup, SWT.PUSH);
			importAllButton.setText("import streams");
			importAllButton
					.setToolTipText("import the integration stream source files information to the database");
			importAllButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
					true, false));

			newDbButton.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					IStorage storage = new TeneoHibernateStorage();
					storage.createNewModelDB();
					if (!storage.isInitialized()) {
						storage.initDataStore();
					}
					MessageDialog
							.open(MessageDialog.INFORMATION,
									getShell(),
									"New database",
									"the new database schema is created and initliazed",
									SWT.NONE);
				}

			});

			clearButton.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					boolean confirm = MessageDialog
							.openConfirm(
									getShell(),
									"Delete the database",
									"Are you sure that you want to drop the existing database? \t "
											+ "If you confirm, the database, together with its data, will be deleted permanently");
					if (confirm) {
						TeneoHibernateStorage storage = new TeneoHibernateStorage();
						storage.dropDatabase();
					} else {
						MessageDialog.open(MessageDialog.INFORMATION,
								getShell(), "Canceled",
								"The operation cancels", SWT.NONE);
					}
				}

			});

			importAllButton
					.addSelectionListener(new ImportStreamsButtonHandler());

		}

	}

	private class ImportStreamsButtonHandler extends SelectionAdapter {

		@Override
		public void widgetSelected(SelectionEvent e) {
			IStorage storage = new TeneoHibernateStorage();
			try {
				if(!storage.isConnected()){
					storage.createNewModelDB();
				}
			} catch (ClassNotFoundException e2) {
				MessageDialog.open(MessageDialog.INFORMATION, getShell(), "Class Not Found", e2.getMessage(), SWT.NONE);
			} catch (SQLException e2) {
				MessageDialog.open(MessageDialog.INFORMATION, getShell(), "SQLException", e2.getMessage(), SWT.NONE);
			}
			boolean confirm = MessageDialog
					.openConfirm(
							getShell(),
							"Import Sources",
							"You are going to import the integration stream source files information to the database, \n "
									+ "Before you click OK, make sure that you start the clearcase views of all integration streams");

			if (confirm) {
				
				Project project = ModelFactory.eINSTANCE.createProject();
				project.setName("PF91"); /* TODO: hard code */			
				storage.saveOrUpdateEntity(project);
				TableItem[] items = streamTable.getItems();
				StreamAnalyzer analyzer;
				for (TableItem item : items) {
					Stream stream = ModelFactory.eINSTANCE.createStream();
					stream.setName(item.getText(0));
					stream.setSourcePath(item.getText(1));
					
					DateFormat formatter = new SimpleDateFormat("yyyy");
					try {
						stream.setCreateDate((Date) formatter.parse(item
								.getText(2)));
					} catch (ParseException e1) {
						MessageDialog.open(
								ERROR,
								getShell(),
								"Error in parsing date",
								item.getText(2)
										+ " is not the format of yyyy! \n"
										+ e1.getMessage(), SWT.NONE);
						e1.printStackTrace();
					}
					project.getStreams().add(stream);
					storage.saveOrUpdateEntity(stream);
					
					/* TODO: import all the source paths */
				}

			}
		}

	}

	private void createStreamTableGroup() {
		if (fieldEditorParent != null) {
			Group tableGroup = new Group(fieldEditorParent.getParent(),
					SWT.NONE);
			tableGroup.setText("Import streams");
			GridLayout gridLayout = new GridLayout();
			gridLayout.numColumns = 3;
			tableGroup.setLayout(gridLayout);
			GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
			tableGroup.setLayoutData(gridData);
			streamTable = new Table(tableGroup, SWT.MULTI | SWT.BORDER
					| SWT.FULL_SELECTION);
			gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
			gridData.horizontalSpan = 3;
			streamTable.setLayoutData(gridData);

			streamTable.setLinesVisible(true);
			streamTable.setHeaderVisible(true);

			for (int i = 0; i < TITLES.size(); i++) {
				TableColumn column = new TableColumn(streamTable, SWT.NONE);
				column.setText(TITLES.get(i));
			}

			int count = STREAMS.size();
			for (int i = 0; i < count; i++) {
				TableItem item = new TableItem(streamTable, SWT.NONE);
				item.setText(0, STREAMS.get(i).get(0));
				item.setText(1, STREAMS.get(i).get(1));
				item.setText(2, STREAMS.get(i).get(2));
			}
			for (int i = 0; i < TITLES.size(); i++) {
				streamTable.getColumn(i).pack();
			}

			Button addButton = new Button(tableGroup, SWT.PUSH);
			addButton.setText("add...");
			addButton.addSelectionListener(new SelectionAdapter() {
				// TODO add a stream to the configuration page
			});
			Button removeButton = new Button(tableGroup, SWT.PUSH);
			removeButton.setText("remove");
			removeButton.addSelectionListener(new SelectionAdapter() {
				// TODO remove a stream to the configuration page
			});
		}
	}

}
